package com.myt.matp.gui;

import com.myt.matp.core.Event;

import com.myt.matp.utils.Edit;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Font;
import java.lang.Math;

public class UIEdit extends UIScroll {

    public static final int FLAG_CENTERED = 0x00000001;

    public static final int TYPE_MODE_ALPHANUMERIC = 1;
    public static final int TYPE_MODE_NUMERIC = 2;

    public static final int TYPE_CASE_UPPER = 1;
    public static final int TYPE_CASE_LOWER = 2;

    private static final int PERIOD_CURSOR = 500;
 
    // The sub-editor
    protected Edit m_SubEditor = new Edit(160);

    // Font
    private int m_Face = 0;
    private int m_Style = 0;
    private int m_Size = 0;

    // Behaviour
    private int m_PointPct = 40;
    private boolean m_Flicker = true;

    // Paint Text
    private Image m_TextImage = null;

    // The cursor
    private boolean m_DisplayCursor = true;
    private int m_LastCursorColumn = 0;
    private int m_LastCursorRow = 0;

    // Performance control
    private boolean m_ReWraping = true;
    private boolean m_PaintText = true;

    // Control
    private int m_LastKeyPressed = 0;
    private int m_CurrKeyPressed = 0;
    private int m_LastPointCol = 0;

    // Typing control
    private boolean m_TypeInit = false;
    private boolean m_TypeDone = true;
    private int m_TypeCase = TYPE_CASE_LOWER;
    private int m_TypeMode = TYPE_MODE_ALPHANUMERIC;
    private int m_TypeTick = 0;
    private int m_TypeKey = 0;
    private int m_TypeChar = 0;
    private final char m_TypeLayout[][] = {
        {' ', '0'},
        {'.', ',', '?', '!', '+', '-', '_', '1'},
        {'a', 'b', 'c', '2'},
        {'d', 'e', 'f', '3'},
        {'g', 'h', 'i', '4'},
        {'j', 'k', 'l', '5'},
        {'m', 'n', 'ñ', 'o', '6'},
        {'p', 'q', 'r', 's', '7'},
        {'t', 'u', 'v', '8'},
        {'w', 'x', 'y', 'z', '9'},
        {'#'},
        {'*'},
    };

    protected UIEdit(int id, GUI gui) {
	super(id, gui);
    }

    public int getType() {
	return UIWidget.EDIT;
    }

    protected final void resized() {
 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".resized() {");
	//#endif

	// Create Image text
	m_TextImage = Image.createImage(getWidth(), getHeight());
	// Set scroll bars dimension
	if (hasVerticalScroll()) {
	    UIScrollBar sb = getVerticalScrollBar();
	    sb.resize(getViewWidth(), getViewHeight());
	}
	// Is necesary rewrapiing all
	joinLines();
 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif
    }

    protected int getMinHeight() {
	return super.getMinHeight() + getFontHeight();
    }

    public final void setText(String text) {
	m_SubEditor.setString(text);
	joinLines();
	resetVerticalFrame();
	resetPaintText();
	redraw();
    }

    public final void showCursor(boolean show) {
	m_DisplayCursor = show;
    }

    protected void changeFocus(boolean value) {
	if (value) {
	    initAlarm(PERIOD_CURSOR);
	}
	else {
	    killAlarm();
	}
	m_OnFocus = value;
    }

    public final int getCursorRow() {
	return getViewY() + getPointRow() * getFontHeight();
    }

    public final int getCursorColumn() {
 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".getCursorColumn() {");
	//#endif

	int point;
	int ret = getViewX();

	point = m_SubEditor.getPoint();
	setPointCol(0);
 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tstart = " + m_SubEditor.getPoint());
	//# System.out.println("\tend = " + point);
	//#endif
	ret += m_Gui.getCharsWidth(m_SubEditor, 
				   m_SubEditor.getPoint(), 
				   point - m_SubEditor.getPoint());

	m_SubEditor.setPoint(point);

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif

	return ret;
    }

    public final void setCursor(int count) {
	setPoint(count);
	// Reframing
	resetVerticalFrame();
	// Repaing
	resetPaintText();
	redraw();
    }

    public final int getCursor(boolean display) {
	return getPoint();
    }

    private void setPoint(int count) {
	m_SubEditor.setPointAtStart();
	while ((count > 0) && !m_SubEditor.atEnd()) {
	    if (!m_SubEditor.isCharEqualTo(Edit.CHAR_BRKLINE)) {
		count--;
	    }
	    m_SubEditor.movePoint(1);
	}
    }

    private int getPoint() {
	int point;
	int ret;

	point = m_SubEditor.getPoint();
	ret = point;
	while (!m_SubEditor.atStart()) {
	    if (m_SubEditor.isCharEqualTo(Edit.CHAR_BRKLINE)) {
		ret--;
	    }
	    m_SubEditor.movePoint(-1);
	}
	
	m_SubEditor.setPoint(point);

	return ret;
    }

    public final void setFont(int face, int style, int size) {
	m_Face = face;
	m_Style = style;
	m_Size = size;
    }

    public final int getFontFace() {
	return m_Face;
    }

    public final int getFontStyle() {
	return m_Style;
    }

    public final int getFontSize() {
	return m_Size;
    }

    public final void setTypeMode(int mode) {
	m_TypeMode = mode;
    }

    public final int getTypeMode() {
	return m_TypeMode;
    }

    public final void setTypeCase(int tcase) {
	m_TypeMode = tcase;
    }

    public final int getTypeCase() {
	return m_TypeCase;
    }

    public final int getFontHeight() {
	m_Gui.setFont(m_Face, m_Style, m_Size);
	return m_Gui.getFontHeight();
    }

    private int getNumLinesWindow() {
	return (getViewHeight() / getFontHeight());
    }

    private void breakLines() {
	int x;
	int dc;
	int vw;

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".breakLines() {");
	//#endif

	// save point
	int point = m_SubEditor.getPoint();

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\trecording point = " + point);
	//#endif

	// width 
	vw = getViewWidth();

	// find the first mark of formated text
	m_SubEditor.findFirstInBackward(Edit.CHAR_BRKLINE);

	// start format
	while (!m_SubEditor.atEnd()) {
	    x = 0;
	    dc = m_Gui.getCharWidth(m_SubEditor.getChar());
	    // find next linebreak
	    while (x + dc <= vw) {
		// next char
		m_SubEditor.movePoint(1);
		// if end buffer ...
		if (m_SubEditor.atEnd()) {
		    break;
		}
		// if \n ...
		if (m_SubEditor.isCharEqualTo(Edit.CHAR_NEWLINE)) {
		    // break line
		    m_SubEditor.movePoint(1);
		    break;
		}
		// If \r ...
		if (m_SubEditor.isCharEqualTo(Edit.CHAR_BRKLINE)) {
		    // modify point location recorded
		    if (m_SubEditor.getPoint() <= point) {
			point--;
		    }
		    m_SubEditor.delete(1);
		}
 		x += dc;
 		dc = m_Gui.getCharWidth(m_SubEditor.getChar());
	    }
	    if (x + dc > vw) {
		//#ifdef DEBUG_UIEDIT
		//# System.out.println("\tinserting breakline ...");
		//#endif
		// modify point location recorded
		if (m_SubEditor.getPoint() <= point) {
		    //#ifdef DEBUG_UIEDIT
		    //# System.out.println("\tincrementing point location recorded");
		    //#endif
		    point++;
		}
		m_SubEditor.insertChar(Edit.CHAR_BRKLINE);
	    }
	} 

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\trestoring point = " + point);
	//# System.out.println("\tm_SubEditor.getPoint() = " + m_SubEditor.getPoint());
	//# System.out.println("\tm_SubEditor.end() = " + m_SubEditor.end());
	//#endif

	// restore point
	m_SubEditor.setPoint(point);

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif
    }

    private void joinLines() {
	int point = getPoint();
	m_SubEditor.setPointAtStart();
	while (!m_SubEditor.atEnd()) {
	    if (isControlCharacter(m_SubEditor.getChar())) {
		m_SubEditor.delete(1);
	    }
	    else {
		m_SubEditor.movePoint(1);
	    }
	}
	setPoint(point);
    }

    protected boolean isControlCharacter(char c) {
	return (c == Edit.CHAR_BRKLINE ? true : false);
    }

    private int getWidthLine() {
	int ret = 0;
	int point = m_SubEditor.getPoint();
	do {
	    ret += m_Gui.getCharWidth(m_SubEditor.getChar());
	    m_SubEditor.movePoint(1);
	} while (!m_SubEditor.isPointOnBreakLine() && !m_SubEditor.atEnd());

	m_SubEditor.setPoint(point);
	return ret;
    }

    protected final void paintUIScroll(MGraphics g) {
	// Paint UIEdit text
	paintText(g);
	// Paint cursor
	paintPoint(g);
    }
    
    public final void movePoint(int count) {
	int step = (count < 0) ? 1 : -1; 

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".movePoint() {");
	//#endif

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tcount = " + count);
	//# System.out.println("\tstep = " + step);
	//#endif

	while (count != 0) {
	    m_SubEditor.movePoint(-step);
	    if (!m_SubEditor.isCharEqualTo(Edit.CHAR_BRKLINE)) {
		count += step;
	    }
	}
	m_TypeInit = false;

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tm_SubEditor.end() = " + m_SubEditor.end());
	//# System.out.println("\tm_SubEditor.getPoint() = " + m_SubEditor.getPoint());
	//#endif

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif
    }

    public final void delete(int count) {
	int step = (count < 0) ? 1 : -1; 
	while (count != 0) {
	    m_SubEditor.movePoint(-step);
	    if (!m_SubEditor.isCharEqualTo(Edit.CHAR_BRKLINE)) {
		count += step;
	    }
	    m_SubEditor.delete(step);
	}
    }


    private void putChar(char c) {
	int dc = m_Gui.getCharWidth(c);

	// Efficient wrapping and reframing
	if (!m_SubEditor.atEnd() ||
	    (m_SubEditor.atEnd() && 
	     (m_LastCursorColumn + dc > getViewX() + getViewWidth()))) {
	    // Recalcutate wrapping
	    resetWrapping();
	    if (getPointRow() == getNumLinesWindow() - 1) {
		// Recalculate framing
		resetVerticalFrame();
	    }
	}
	resetVerticalRedisplay();

	// Put character
	m_SubEditor.putChar(c);

	// Area to repaint
	redraw(getViewX(), 
	       m_LastCursorRow, 
	       getViewWidth(), 
	       getViewHeight() - (m_LastCursorRow - getViewY()));
    }

    private void delChar() {
	// Efficient wrapping and reframing
	if (!m_SubEditor.atEnd()) {
	    resetWrapping();
	}
	if (m_SubEditor.getPoint() == getFrame()) {
	    resetVerticalFrame();
	}
	resetVerticalRedisplay();

	// delete char
	delete(-1);
	    
	// Area to repaint
	int prevCursorRow = Math.max(getViewY(), m_LastCursorRow - getFontHeight());
	redraw(getViewX(),
	       prevCursorRow,
	       getViewWidth(),
	       getViewHeight() - (prevCursorRow - getViewY()));
    }

    private void replaceChar(char c) {

	// Repaint visible area
	resetPaintText();

	// Replace character
	m_SubEditor.replaceChar(c);

	// area to repaint
	redraw(getViewX(), 
	       m_LastCursorRow, 
	       getViewWidth(), 
	       getFontHeight());
    }

    public final int getPointCol() {
	int ret = 0;
	int point = m_SubEditor.getPoint();

	do {
	    m_SubEditor.movePoint(-1);
	    if (m_SubEditor.atStart() ||
		m_SubEditor.isPointOnBreakLine()) {
		break;
	    }
	    ret++;
	} while (true);

	m_SubEditor.setPoint(point);

	return ret;
    }

    public final int getPointRow() {
	int point;
	int ret = 0;

	point = m_SubEditor.getPoint();

	m_SubEditor.setPoint(getFrame());
	do {
	    m_SubEditor.findFirstInForewardBreakLine();
	    // Because the point could stay on Edit.CHAR_NEWLINE
	    // we need use >= comparation
	    if (m_SubEditor.getPoint() >= point) {
		break;
	    }
	    ret++;
	    m_SubEditor.movePoint(1);
	} while (!m_SubEditor.atEnd());

	m_SubEditor.setPoint(point);

	return ret;
    }

    public final void setPointCol(int col) {

	if (!m_SubEditor.atStart()) {

	    // Because the point could stay on Edit.CHAR_NEWLINE
	    if (m_SubEditor.isCharEqualTo(Edit.CHAR_NEWLINE)) {
		m_SubEditor.movePoint(-1);
	    }

	    // Point the start of the line
	    m_SubEditor.findFirstInBackwardBreakLine();

	    // Set point at col 0
	    if (m_SubEditor.isPointOnBreakLine()) {
		m_SubEditor.movePoint(1);
	    }
	}

	while (col > 0) {
	    if (m_SubEditor.isPointOnBreakLine()) {
		if (m_SubEditor.isCharEqualTo(Edit.CHAR_BRKLINE)) {
		    m_SubEditor.movePoint(-1);
		}
		break;
	    }
	    m_SubEditor.movePoint(1);
	    col--;
	}
    }


    private void findPreviusLine() {

	if (m_SubEditor.isCharEqualTo(Edit.CHAR_NEWLINE)) {
	    m_SubEditor.movePoint(-1);
	}

	m_SubEditor.findFirstInBackwardBreakLine();

	if (m_SubEditor.isCharEqualTo(Edit.CHAR_BRKLINE)) {
	    m_SubEditor.movePoint(-1);
	}
    }

    private void findNextLine() {

	m_SubEditor.findFirstInForewardBreakLine();
	m_SubEditor.movePoint(1);

    }
    
    public final void moveLine(int count) {
 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".moveLine() {");
	//#endif

	int point = m_SubEditor.getPoint();
	int step = (count < 0) ? 1 : -1; 

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tm_CurrKeyPressed = " + m_CurrKeyPressed);
	//# System.out.println("\tm_LastKeyPressed = " + m_LastKeyPressed);
	//#endif

	if (m_CurrKeyPressed != m_LastKeyPressed) {
	    m_LastPointCol = getPointCol();
	}


 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tpoint = " + point);
	//#endif

	while (count != 0) {
	    if (count < 0) {
		findPreviusLine();
	    } else {
		findNextLine();
	    }
	    count += step;
	}

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tm_LastPointCol = " + m_LastPointCol);
	//# System.out.println("\tm_SubEditor.getPoint() = " + getPoint());
	//#endif

	m_LastPointCol = ((point == m_LastPointCol) && (step == 1)) ? 0 : m_LastPointCol;

	if (!m_SubEditor.atEnd()) {
	    setPointCol(m_LastPointCol);
	}

	m_TypeInit = false;

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif
    }

    private void paintText(MGraphics g) {

	if (m_PaintText) {
	    Graphics jg;
	    // save original context device
	    jg = g.getGraphics();
	    // painting on backup image
	    g.setGraphics(m_TextImage.getGraphics());
	    g.translate(-getPosX(), -getPosY());
	    g.setClip(jg.getClipX(), 
		      jg.getClipY(), 
		      jg.getClipWidth(),
		      jg.getClipHeight());
	    paintBackground(g);
	    paintTextToImage(g);
	    g.setGraphics(jg);
	    m_PaintText = false;
	}

	g.setClip(getViewX(), getViewY(), 
		  getViewWidth(), getViewHeight());
	g.drawImage(m_TextImage, 
		    getPosX(), 
		    getPosY(),  
		    Graphics.TOP | Graphics.LEFT);
    }

    protected final void resetPaintText() {
	m_PaintText = true;
    }
    

    protected final void resetWrapping() {
	m_ReWraping = true;
	resetPaintText();
    }

    protected void paintTextToImage(MGraphics g) {
	int point;
	int x0 = 0;
	int y = 0;
	int fh = 0;
	int dx = 0;
	int vw = 0;

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".paintTextToImage() {");
	//#endif

	point = m_SubEditor.getPoint();

	paintBackground(g);	
	g.setColor(getColor(COLOR_FOREGROUND));
	g.setFont(m_Face, m_Style, m_Size);

	m_SubEditor.setPoint(getFrame());
	fh = getFontHeight();
	vw = getViewWidth();
	y = getViewY();

	while ((m_SubEditor.getPoint() - getFrame() < getRedisplay()) &&
	       !m_SubEditor.atEnd()) {
	    x0 = getViewX();
	
	    if ((dx == 0) && hasFlags(FLAG_CENTERED)) {
		x0 += ((vw - getWidthLine()) / 2);
	    }

	    if (!m_SubEditor.isPointOnBreakLine()) {
		//#ifdef DEBUG_UIEDIT
		//# System.out.print(m_SubEditor.getChar());
		//#endif

		// Print char
		g.drawChar(m_SubEditor.getChar(),
			   x0 + dx, 
			   y, 
			   Graphics.TOP | Graphics.LEFT);

		dx += m_Gui.getCharWidth(m_SubEditor.getChar());
	    }
	    else{
		//#ifdef DEBUG_UIEDIT
		//# System.out.print("\n");
		//#endif
		dx = 0;
		y += fh;
	    }

	    m_SubEditor.movePoint(1);	   
	}

	m_SubEditor.setPoint(point);

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif
    }

    private void paintPoint(MGraphics g) {
	if (m_DisplayCursor && m_Flicker) {
	    // Set color
	    g.setColor(0);
	    // Set Stroke style
	    g.setStrokeStyle(Graphics.SOLID);
	    // recording last position
	    m_LastCursorRow = getCursorRow();
	    m_LastCursorColumn = getCursorColumn();
	    // Paint cursor
	    g.fillRect(m_LastCursorColumn - 1,
		       m_LastCursorRow,
		       getPointWidth(),
		       getPointHeight()
		       );
	}
    }

    private int getPointWidth() {
	return 2;
    }

    private int getPointHeight() {
	return m_Gui.getFontHeight();
    }

    public boolean dispatchEvent(final Event e) {
	boolean ret = true;
	if (!dispatchEventUIEdit(e)) {
	    ret = super.dispatchEvent(e);
	}
	return ret;
    }

    public boolean dispatchEventUIEdit(final Event e) {
	boolean ret = false;

	switch (e.getId()) {
	case Event.UI_KEY_PRESSED:
	    ret = eventUIKeyPressed(e);
	    break;
	case Event.UI_KEY_REPEATED:
	    break;
	case Event.UI_KEY_RELEASED:
	    ret = eventUIKeyReleased(e);
	    break;
	case Event.SC_ALARM:
	    ret = eventSCAlarm(e);
	    break;
	}

	return ret;
    }

    /*
     * Events
     *
     */
    private boolean eventUIKeyPressed(final Event e) {
	boolean ret = true;

	m_CurrKeyPressed = e.getWParam();

	switch (e.getWParam()) {
	case GUI.KEY_POUND:
	case GUI.KEY_STAR:
	case GUI.KEY_0:
	case GUI.KEY_1:
	case GUI.KEY_2:
	case GUI.KEY_3:
	case GUI.KEY_4:
	case GUI.KEY_5:
	case GUI.KEY_6:
	case GUI.KEY_7:
	case GUI.KEY_8:
	case GUI.KEY_9:
	    ret = cmdTypeCharacter(e.getWParam(), e.getId());
	    break;
	}

	return ret;
    }

    private boolean eventUIKeyReleased(final Event e) {
	boolean ret = true;

	switch (e.getWParam()) {
	case GUI.KEY_POUND:
	case GUI.KEY_STAR:
	case GUI.KEY_0:
	case GUI.KEY_1:
	case GUI.KEY_2:
	case GUI.KEY_3:
	case GUI.KEY_4:
	case GUI.KEY_5:
	case GUI.KEY_6:
	case GUI.KEY_7:
	case GUI.KEY_8:
	case GUI.KEY_9:
	    ret = cmdTypeCharacter(e.getWParam(), e.getId());
	    break;
	case GUI.KEY_SOFTRIGHT:
	    ret = cmdDeleCharacter();
	    break;
	case GUI.KEY_LEFT:
	    cmdMovePointLeft();
	    break;
	case GUI.KEY_RIGHT:
	    cmdMovePointRight();
	    break;
	case GUI.KEY_DOWN:
	    cmdMoveLineDown();
	    break;
	case GUI.KEY_UP:
	    cmdMoveLineUP();
	    break;
	default:
	    ret = false;
	    break;
	}

	m_LastKeyPressed = m_CurrKeyPressed;

	return ret;
    }

    private boolean eventSCAlarm(final Event e) {
	if (m_TypeInit) {
	    m_TypeTick++;
	    if (m_TypeDone && (m_TypeTick > 3)) {
		postEvent(Event.UI_KEY_RELEASED, GUI.KEY_RIGHT);
	    }
	}
	m_Flicker = !m_Flicker;
	redraw();
	return true;
    }

    protected int computeContent() {
	return m_SubEditor.getNumChars();
    }

    protected int computeFrame() {	
	int point;
	int nl;
	int frame;
	int newStartLoc = 0;
	int cnt;

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".computeFrame() {");
	//#endif

	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tframing ...");
	//#endif

	if (m_ReWraping) {
	    breakLines();
	    m_ReWraping = false;
	}

	point = m_SubEditor.getPoint();

	// Because the point could stay on Edit.CHAR_NEWLINE
	if (m_SubEditor.isCharEqualTo(Edit.CHAR_NEWLINE)) {
	    m_SubEditor.movePoint(-1);
	}
                     
	nl = getNumLinesWindow();

	// Go backward at most nl breaklines
	m_SubEditor.findFirstInBackwardBreakLine();
	for (cnt = 0; cnt < (nl - 1); cnt++) {       

	    //#ifdef DEBUG_UIEDIT
	    //# System.out.println("\tcnt = " + cnt);
	    //#endif

	    // Stop at start of the buffer
	    if (m_SubEditor.atStart()) {
		break;
	    }

	    // record where a fresh screen would be start
	    // just in case we need it
	    if ((cnt + 1) == m_PointPct * getNumLinesWindow() / 100) {
		newStartLoc = m_SubEditor.getPoint();
	    }

	    m_SubEditor.movePoint(-1);
	    m_SubEditor.findFirstInBackwardBreakLine();
	}

	// was the window moved?
	if (cnt >= (nl - 1)) {
	    m_SubEditor.setPoint(newStartLoc);
	}
	
	if (m_SubEditor.isPointOnBreakLine() &&
	    !m_SubEditor.atStart()) {
	    m_SubEditor.movePoint(1);
	}

	frame = m_SubEditor.getPoint();

	m_SubEditor.setPoint(point);

	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tframe = " + frame);
	//#endif

	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif
	
	return frame;
    }

    protected int computeRedisplay(int frame) {
	int point;
	int redisplay;
	int nl;

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println(getClass().getName() + ".computeRedisplay() {");
	//#endif
	
	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tredisplaying ...");
	//#endif

	if (m_ReWraping) {
	    breakLines();
	    m_ReWraping = false;
	}

	point = m_SubEditor.getPoint();

	nl = getNumLinesWindow();

	m_SubEditor.findFirstInForewardBreakLine();
	for (int cnt = getPointRow(); cnt < (nl - 1); cnt++) {

	    // Stop at start of the buffer
	    if (m_SubEditor.atEnd()) {
		break;
	    }

	    m_SubEditor.movePoint(1);
	    m_SubEditor.findFirstInForewardBreakLine();
	}

	if (m_SubEditor.isPointOnBreakLine()) {
	    m_SubEditor.movePoint(-1);
	}	
	
	redisplay = m_SubEditor.getPoint() - frame + 1;

	m_SubEditor.setPoint(point);

	resetPaintText();

	//#ifdef DEBUG_UIEDIT
	//# System.out.println("\tredisplay = " + redisplay);
	//#endif

 	//#ifdef DEBUG_UIEDIT
	//# System.out.println("}");
	//#endif
	
	return redisplay;
    }

    /*
     * Commands
     *
     */
    private void cmdMovePointLeft() {
	if ((getFrame() != m_SubEditor.start()) &&
	    (getFrame() == m_SubEditor.getPoint())) {
	    resetVerticalFrame();
	}
	movePoint(-1);
	redraw();
    }

    private void cmdMovePointRight() {
	if ((getFrame() + getRedisplay() != m_SubEditor.end()) &&
	    (getFrame() + getRedisplay() == m_SubEditor.getPoint()) &&
	    (getPointRow() == (getNumLinesWindow() - 1))) {
	    resetVerticalFrame();
	}
	movePoint(1);
	redraw();
    }

    private void cmdMoveLineUP() {
	if (m_SubEditor.atStart()) {
	    // Tab event
	} else {
	    if ((getFrame() != m_SubEditor.start()) &&
		(getPointRow() == 0)) {
		resetVerticalFrame();
	    }
	    moveLine(-1);
	    redraw();
	}
    }

    private void cmdMoveLineDown() {
	if (m_SubEditor.atEnd()) {
	    // Tab event
	} else {
	    if ((getFrame() + getRedisplay() != m_SubEditor.end()) &&
		(getPointRow() == (getNumLinesWindow() - 1))) {
		resetVerticalFrame();
	    }
	    moveLine(1);
	    redraw();
	}
    }

    private boolean cmdDeleCharacter() {
	if (!m_TypeInit && !m_SubEditor.atStart()) {
	    delChar();
	}
	return true;
    }

    private boolean cmdTypeCharacter(int key, int event) {

	switch (event) {
	case Event.UI_KEY_PRESSED:
	    m_TypeDone = false;
	    m_TypeTick = 0;
	    if (!m_TypeInit) {
		m_TypeInit = true;
		m_TypeKey = key;
		putChar(computeCharacter(key, true));
	    }
	    else {
		if (m_TypeKey != key) {
		    m_TypeKey = key;
		    m_SubEditor.movePoint(1);
		    putChar(computeCharacter(key, true));
		}
		else {
		    replaceChar(computeCharacter(key, false));
		}
	    }
	    break;
	case Event.UI_KEY_RELEASED:
	    switch (key) {
	    case GUI.KEY_0:
	    case GUI.KEY_1:
	    case GUI.KEY_2:
	    case GUI.KEY_3:
	    case GUI.KEY_4:
	    case GUI.KEY_5:
	    case GUI.KEY_6:
	    case GUI.KEY_7:
	    case GUI.KEY_8:
	    case GUI.KEY_9:
		m_TypeDone = true;
		if (m_TypeInit && (m_TypeTick > 1)) {
		    m_TypeInit = false;
		    m_TypeTick = 0;
		    int mode = getTypeMode();
		    setTypeMode(TYPE_MODE_NUMERIC);
		    replaceChar(computeCharacter(key, false));
		    m_SubEditor.movePoint(1);
		    setTypeMode(mode);
		}		
	    }
	    break;
	default:
	    break;
	}

	return true;
    }

    /*
     *
     *
     */

    private char computeCharacter(int key, boolean init) {
	char[] chars = null;
	char ret;

	switch (key) {
	case GUI.KEY_POUND:
	    chars = m_TypeLayout[10];
	    break;
	case GUI.KEY_STAR:
	    chars = m_TypeLayout[11];
	    break;
	case GUI.KEY_0:
	case GUI.KEY_1:
	case GUI.KEY_2:
	case GUI.KEY_3:
	case GUI.KEY_4:
	case GUI.KEY_5:
	case GUI.KEY_6:
	case GUI.KEY_7:
	case GUI.KEY_8:
	case GUI.KEY_9:
	    chars = m_TypeLayout[key - GUI.KEY_0];
	    break;
	default:
	    chars = m_TypeLayout[0];
	}

	if (m_TypeMode == TYPE_MODE_NUMERIC) {
	    m_TypeChar = chars.length - 1;
	}
	else {
	    m_TypeChar = (init ? 0 : m_TypeChar + 1);
	}

	if (m_TypeChar == chars.length) {
	    m_TypeChar = 0;
	}

	ret = (m_TypeCase == TYPE_CASE_UPPER ? 
	       Character.toUpperCase(chars[m_TypeChar]) : 
	       chars[m_TypeChar]);

	return ret;
    }

}
